﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServiciosGeograficos.Modelo;
using ServiciosGeograficos.Reconocimiento;
using System.Data;
using ServiciosGeograficos.Persistencia;

namespace ServiciosGeograficos.Servicios
{
    public class Servicios
    {
        private String delimitador = ";";
        private static int DISTANCIA_METROS_PARADAS = 50;
        public static int PROBLEMA_CALLE1 = 1; // No entendi calle 1 - Muestro en sugerenciaCalle1 calles con nombre parecido
        public static int PROBLEMA_CALLE2 = 2; // No entendi calle 2 - Muestro en sugerenciaCalle2 calles con nombre parecido
        public static int PROBLEMA_LINEA = 3; // No entendi linea - Muestro en sugerenciaLinea las lineas-destino que pasan por esa parada
        public static int PROBLEMA_DESTINO = 4; // No entendi destino - Muestro en sugerenciaLinea sugerencias de destino para esa linea
        public static int PROBLEMA_ID_PARADA = 5; // No entendi idParada
        public static int PROBLEMA_ID_PARADA_LINEA_DESTINO = 6; // La linea-destino pasada como pararametro no pasa por la parada idParada pasada como parametro


        public PostgresDAO postgresDAO;

        public Retorno ubicarParada(int tipoMensaje, String calle1, String calle2,
            String linea, String destino, String numeroPuerta, int idParada)
        {
            postgresDAO = new PostgresDAO();
            if (tipoMensaje == 0)
            {   //0: esquina (calle - calle) - linea - destino
                return procesarMensajeCalleCalle(calle1, calle2, linea, destino);
            }
            else if (tipoMensaje == 1)
            {   //1: calle - numero de puerta - linea - destino
                return procesarMensajeCalleNumPuerta(calle1, numeroPuerta, linea, destino);
            }
            else
            {   //2: idParada - linea - destino
                return procesarMensajeIdParada(idParada, linea, destino);
            }
        }

        private Retorno procesarMensajeIdParada(int idParada, String linea, String destino)
        {
            Retorno retorno = new Retorno();
            retorno.idParada = idParada;
            bool encontreLineaDestino = procesarLineaDestino(linea, destino, retorno);
            if (encontreLineaDestino)
            {
                // Valido que existe el idParada que me pasaron
                bool encontre = false;
                String query = "select idParada  from paradas parada";
                query += " where idParada = " + idParada;
                DataSet dataSetParada = postgresDAO.ejecutarQuery(query, "idParada");
                foreach (DataRow row in dataSetParada.Tables["idParada"].Rows)
                {
                    retorno.datosUbicados = true;
                    retorno.idParada = (int)row["idParada"];
                    encontre = true;
                }
                if (!encontre)
                {
                    retorno.tipoError = PROBLEMA_ID_PARADA;
                }
                else
                {
                    // Valido si encontre Linea Destino que el omnibus pase por la parada que corresponde a idParada
                    query = "select idParada  from paradas parada";
                    query += " where bus = '" + retorno.idBus + "'";
                    query += " and idParada = " + idParada;

                    encontre = false;
                    dataSetParada = postgresDAO.ejecutarQuery(query, "lineasParada");
                    foreach (DataRow row in dataSetParada.Tables["lineasParada"].Rows)
                    {
                        retorno.datosUbicados = true;
                        retorno.idParada = (int)row["idParada"];
                        encontre = true;
                    }
                    if (!encontre)
                    {
                        retorno.tipoError = PROBLEMA_ID_PARADA_LINEA_DESTINO;
                    }
                }
            }
            return retorno;
        }


        private Retorno procesarMensajeCalleNumPuerta(String calle1, String numPuerta, String linea, String destino)
        {
            InterpreteCalles interpreteCalles = new InterpreteCalles();
            Retorno retorno = new Retorno();
            bool encontreLineaDestino = procesarLineaDestino(linea, destino, retorno);
            if (encontreLineaDestino)
            {
                // Si encontre la linea entonces me fijo si encuentro las calles 
                DataSet dataSetCalles = interpreteCalles.callePuertas(calle1, numPuerta);
                if (dataSetCalles != null && dataSetCalles.Tables["posiblesCalles"] != null && dataSetCalles.Tables["posiblesCalles"].Rows.Count > 0)
                {
                    foreach (DataRow row in dataSetCalles.Tables["posiblesCalles"].Rows)
                    {
                        retorno.sugerenciaCalle1 += (String)row["nm_calle"] + delimitador;
                    }
                    retorno.tipoError = PROBLEMA_CALLE1;
                }
                else
                {
                    // Entendi los valores calle1, calle2 (y se intersectan) , linea y destino, me fijo si dicha linea pasa por la parada
                    // definida por los puntos calle1 interseccion calle2
                    procesarRespuesta(retorno, dataSetCalles);
                }
            }
            return retorno;
        }

        private Retorno procesarMensajeCalleCalle(String calle1, String calle2, String linea, String destino)
        {
            InterpreteCalles interpreteCalles = new InterpreteCalles();
            Retorno retorno = new Retorno();
            bool encontreLineaDestino = procesarLineaDestino(linea, destino, retorno);
            if (encontreLineaDestino)
            {
                // Si encontre la linea entonces me fijo si encuentro las calles 
                DataSet dataSetCalles = interpreteCalles.calleEsquina(calle1, calle2);
                if (dataSetCalles != null && dataSetCalles.Tables["posiblesEsquinas"] != null && dataSetCalles.Tables["posiblesEsquinas"].Rows.Count > 0)
                {
                    foreach (DataRow row in dataSetCalles.Tables["posiblesEsquinas"].Rows)
                    {
                        retorno.sugerenciaCalle2 += (String)row["nm_calle"] + delimitador;
                    }
                    retorno.tipoError = PROBLEMA_CALLE2;
                }
                else if (dataSetCalles != null && dataSetCalles.Tables["posiblesCalles"] != null && dataSetCalles.Tables["posiblesCalles"].Rows.Count > 0)
                {
                    foreach (DataRow row in dataSetCalles.Tables["posiblesCalles"].Rows)
                    {
                        retorno.sugerenciaCalle1 += (String)row["nm_calle"] + delimitador;
                    }
                    retorno.tipoError = PROBLEMA_CALLE1;
                }
                else
                {
                    // Entendi los valores calle1, calle2 (y se intersectan) , linea y destino, me fijo si dicha linea pasa por la parada
                    // definida por los puntos calle1 interseccion calle2

                    procesarRespuesta(retorno, dataSetCalles);

                }
            }
            return retorno;
        }

        private void procesarRespuesta(Retorno retorno, DataSet dataSetCalles)
        {
            String x_coord = "";
            String y_coord = "";
            foreach (DataRow row in dataSetCalles.Tables["interseccion"].Rows)
            {
                x_coord = "" + (double)row["punto_x"];
                y_coord = "" + (double)row["punto_y"];
            }
            x_coord = x_coord.Replace(",", ".");
            y_coord = y_coord.Replace(",", ".");
            String query = "select id1 as idParada,abs(x - " + x_coord + ") + abs(y - " + y_coord + ") as diferencia from paradas parada";
            query += " where bus = '" + retorno.idBus + "'";
            query += " order by diferencia asc limit 1";
            DataSet dataSetParadaCercana = postgresDAO.ejecutarQuery(query, "paradaCercana");
            foreach (DataRow row in dataSetParadaCercana.Tables["paradaCercana"].Rows)
            {
                double diferencia = (double)row["diferencia"];
                retorno.datosUbicados = true;
                retorno.idParada = (int)row["idParada"];
            }
        }


        private bool procesarLineaDestino(String linea, String destino, Retorno retorno)
        {
            InterpreteLineas interpreteLineas = new InterpreteLineas();
            DataSet dataSetLineas = interpreteLineas.lineaDestino(linea, destino);
            bool encontre = false;
            if (dataSetLineas != null && dataSetLineas.Tables["posiblesLineas"] != null && dataSetLineas.Tables["posiblesLineas"].Rows.Count > 0)
            {
                foreach (DataRow row in dataSetLineas.Tables["posiblesLineas"].Rows)
                {
                    retorno.sugerenciaLinea += (String)row["linea"] + "-" + (String)row["destino"] + delimitador;
                }
                retorno.tipoError = PROBLEMA_LINEA;
            }
            else if (dataSetLineas != null && dataSetLineas.Tables["posiblesDestinos"] != null && dataSetLineas.Tables["posiblesDestinos"].Rows.Count > 0)
            {
                foreach (DataRow row in dataSetLineas.Tables["posiblesDestinos"].Rows)
                {
                    retorno.sugerenciaLinea += (String)row["linea"] + "-" + (String)row["destino"] + delimitador;
                }
                retorno.tipoError = PROBLEMA_DESTINO;
            }
            else if (dataSetLineas != null && dataSetLineas.Tables["lineas"] != null && dataSetLineas.Tables["lineas"].Rows.Count > 0)
            {
                foreach (DataRow row in dataSetLineas.Tables["lineas"].Rows)
                {
                    retorno.idLinea = (int)row["gid"];
                    retorno.idBus = (String)row["idBus"];
                }
                encontre = true;
            }
            return encontre;
        }

        #region Paradas por ejemplo para configurar Alertas

        public DataSet obtenerLineas()
        {
            PostgresDAO daoPostgres = new PostgresDAO();
            String query = "select gid,nombre from lineas";
            return daoPostgres.ejecutarQuery(query, "lineas");
        }

        public List<int> obtenerParadas()
        {
            postgresDAO = new PostgresDAO();
            List<int> retorno = new List<int>();
            String query = "select distinct idParada  from paradas parada order by idParada";
            
            DataSet dataSetParadas = postgresDAO.ejecutarQuery(query, "idParada");
            foreach (DataRow row in dataSetParadas.Tables["idParada"].Rows)
            {
                retorno.Add((int)row["idParada"]);
            }
            return retorno;
        }

        public Coordenada obtenerCoordenadaParada(int idParada)
        {
            postgresDAO = new PostgresDAO();
            
            String query = "select x, y from paradas where idParada = " + idParada.ToString();

            DataSet dataSetParadas = postgresDAO.ejecutarQuery(query, "CoordParada");
            DataRow row = dataSetParadas.Tables["CoordParada"].Rows[0];
            
            
            return new Coordenada((double)row["x"], (double)row["y"]);
        }

        #endregion

    }
}